<?php

namespace common\service;

use common\model\EntityModel;
use common\model\ReviewRequestNodeModel;
use common\model\StatusModel;
use common\model\StepCategoryModel;
use common\model\StepModel;
use common\model\TagModel;
use common\model\TaskModel;
use common\model\TaskWorkOrderModel;
use common\model\UserModel;
use common\model\VersionModel;
use support\SingletonTrait;
use think\module\Module;

/**
 * 个人执行任务列表服务
 */
class PersonalExecuteTaskListService
{

    // 单例工具
    use SingletonTrait;

    public function __construct()
    {
    }

    /**
     * 查询任务最大版本数据
     * @param $taskIdList
     * @param array $filterUserIds
     * @return array
     * @throws \think\Exception
     */
    public function queryMaxVersionData($taskIdList, array &$filterUserIds)
    {
        $versionMap = [];
        $versionIdList = model(VersionModel::class)->where(['link_id' => ['IN', implode(',', $taskIdList)]])->field('max(number),id')->group('link_id')->select();
        $versionIdList = array_column($versionIdList, 'id');
        if (!empty($versionIdList)) {
            $versionList = model(VersionModel::class)
                ->join('review_request ON review_request.link_id = version.id and review_request.module_id = ' . module_by_code('version')['id'], 'LEFT')
                ->where(['version.id' => ['IN', $versionIdList]])
                ->field("version.id,version.link_id,version.number,version.is_pass,version.created,review_request.id as review_request_id,review_request.reviewed")
                ->select();
            $versionList = array_column($versionList, null, 'review_request_id');
            $reviewRequestIdList = array_keys($versionList);

            // 查询下一个审核人 和最后一个审核人信息
            if (!empty($reviewRequestIdList)) {
                $reviewRequestNodeList = model(ReviewRequestNodeModel::class)->where(['review_request_id' => ['IN', implode(',', $reviewRequestIdList)]])->select();
                $reviewRequestNodeListGrouped = array_group_by($reviewRequestNodeList, 'review_request_id');
                foreach ($reviewRequestNodeListGrouped as $reviewRequestId => $reviewRequestNodeList) {
                    $nextReviewerUserId = $lastReviewerUserId = 0;
                    foreach ($reviewRequestNodeList as $reviewRequestNode) {
                        if ($reviewRequestNode['is_reviewed'] === 'yes') {
                            $lastReviewerUserId = $reviewRequestNode['real_reviewer'];
                        }
                        if ($nextReviewerUserId === 0 && $reviewRequestNode['is_reviewed'] === 'no') {
                            $nextReviewerUserId = $reviewRequestNode['plan_reviewer'];
                        }
                    }
                    if ($nextReviewerUserId > 0) {
                        $filterUserIds[$nextReviewerUserId] = $nextReviewerUserId;
                    }
                    if ($lastReviewerUserId > 0) {
                        $filterUserIds[$lastReviewerUserId] = $lastReviewerUserId;
                    }
                    $versionList[$reviewRequestId]['next_reviewer_user_id'] = $nextReviewerUserId;
                    $versionList[$reviewRequestId]['last_reviewer_user_id'] = $lastReviewerUserId;
                }
            }
            $versionMap = array_column($versionList, null, 'link_id');
        }
        return $versionMap;
    }

    /**
     * 获取个人执行任务列表
     * @param $param
     * @param int $userId
     * @param int $tenantId 当前租户id
     * @return array
     * @throws \Exception
     */
    public function getPersonalExecuteTaskList($param, int $userId, int $tenantId)
    {
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $order = $param['order'] ?? "entity.initial_episode_code ASC,entity.showings_number ASC,entity.name ASC";
        $abnormal = $param['filter']['abnormal'] ?? false;
        $makingTodo = $param['filter']['making_todo'] ?? false;
        $waitAbnormal = $param['filter']['wait_abnormal'] ?? false;
        $isFilterOverdue = $param['filter']['is_filter_overdue'] ?? false;
        $entityCategoryFilter = $param['filter']['category'] ?? false;
        $entityGradeFilter = $param['filter']['grade'] ?? false;
        unset($param['filter']['making_todo'], $param['filter']['abnormal'], $param['filter']['is_filter_overdue'], $param['filter']['wait_abnormal'], $param['filter']['category'], $param['filter']['grade']);

        // 默认字段
        $fields = [
            "task.id", "task.name", "task.code", "task.man_hour", "task.frame_range", "task.timecode", "task.type", "task.step_type",
            "task.step_category_id", "task.step_id", "task.entity_id", "task.plan_start_time", "task.plan_end_time", "task.plan_duration", "task.department_id",
            "task.description", "task.assignee", "task.executor", "task.created_by", "task.created", "task.actual_man_hour", "task.task_status", "task.task_tag",
            "entity.id", "entity.name", "entity.code", "entity.json", "entity.initial_episode_code", "entity.project_id", "entity.showings_number",
            "entity.module_id", "entity.entity_id", "entity.entity_module_id", "entity.step_workflow_id",
            "module.id", "module.name", "module.code", "project.id", "project.name", "project.code", "project.type", "task.json"
        ];

        //支持外部字段追加
        if (empty($param['fields'])) {
            $param['fields'] = $fields;
        } else {
            $param['fields'] = array_merge($fields, explode(',', $param['fields']));
        }
        $param['fields'] = implode(',', $param['fields']);

        if (empty($param['page'])) {
            // 默认分页数量
            $param['page'] = [1, C("database.database_max_select_rows")];
        }
        // 全部项目 工作台移除空project_id
        if (isset($param['filter']['task.project_id']) && empty($param['filter']['task.project_id'])) {
            unset($param['filter']['task.project_id']);
        }

        if ($entityGradeFilter) {
            $param['filter']["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.',module.code,'_grade')))"] = $entityGradeFilter;
        }

        if ($entityCategoryFilter) {
            $param['filter']["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.',module.code,'_category')))"] = $entityCategoryFilter;
        }


        // 增加当前用户 executor id
        $param['filter'][] = [
            'task.executor' => $userId,
            'task.step_type' => 'step',
            'task.executor_tenant_id' => $tenantId,
        ];

        $firstPage = $page[0] == 1;
        $activeTaskItem = null;
        $timelogTaskId = 0;
        $isFirstActiveTask = false;
        // 排除当前时间日志,只在第一页置顶
        $timelogTaskData = TimelogService::getInstance()->getPersonalTimer($userId, 'task');
        if (!empty($timelogTaskData)) {
            $timelogTaskId = $timelogTaskData['link_id'];
            $firstParam = $param;
            $firstParam['filter']['task.id'] = $timelogTaskId;
            $activeTaskItem = model(TaskModel::class)
                ->join('entity on entity.id = task.entity_id', 'LEFT')
                ->join('module on module.id = entity.module_id', 'LEFT')
                ->join('project on project.id = task.project_id', 'LEFT')
                ->join("status as task_status ON task_status.id = JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))", 'LEFT')
                ->where($firstParam['filter'])
                ->field(build_complex_query_fields($fields, '__'))
                ->find();
            if (!empty($activeTaskItem)) {
                $param['filter'][] = ['task.id' => ['neq', $timelogTaskId]];
                $isFirstActiveTask = $firstPage;
            }
        }

        // 制作待办
        if ($makingTodo) {
            $projectList = ProjectService::getInstance()->getUserProjectList($userId, ['param' => ['project_status' => 'inprogress']]);
            $projectIds = array_column(array_column($projectList['rows'], 'project'), 'id');
            if (empty($param['filter']['task.project_id'])) {
                $param['filter']['task.project_id'] = ['IN', $projectIds];
            }
        }

        // 异常任务
        if ($abnormal) {
            $abnormalList = model(TaskWorkOrderModel::class)->where(['status' => '0', 'tenant_id' => $tenantId])->group("task_id")->select();
            $abnormalId = array_column($abnormalList, 'task_id');
            $param['filter']['task.id'] = ['IN', $abnormalId];
            $param['filter']['task.executor'] = $userId;
        }

        // 待处理异常任务
        if ($waitAbnormal) {
            if (empty($param['filter']['task.project_id'])) {
                return [];
            }
            $abnormalList = model(TaskWorkOrderModel::class)
                ->where(['status' => '0', 'tenant_id' => $tenantId, 'project_id' => $param['filter']['task.project_id']])
                ->group("task_id")->select();
            if (empty($abnormalList)) {
                return [];
            }
            $abnormalId = array_column($abnormalList, 'task_id');
            $param['filter']['task.id'] = ['IN', $abnormalId];
            $param['filter']['task.executor'] = $userId;
        }


        // 是否逾期
        if ($isFilterOverdue) {
            $param['filter']['_string'] = "task.plan_end_time > 0 and task.plan_end_time <= " . time();
        }

        $taskData = [];
        $taskData['total'] = model(TaskModel::class)
            ->join('entity on entity.id = task.entity_id', 'LEFT')
            ->join('module on module.id = entity.module_id', 'LEFT')
            ->join('project on project.id = task.project_id', 'LEFT')
            ->join("status as task_status ON task_status.id = JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))", 'LEFT')
            ->where($param['filter'])
            ->count();
        $taskData['rows'] = model(TaskModel::class)
            ->join('entity on entity.id = task.entity_id', 'LEFT')
            ->join('module on module.id = entity.module_id', 'LEFT')
            ->join('project on project.id = task.project_id', 'LEFT')
            ->join("status as task_status ON task_status.id = JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))", 'LEFT')
            ->where($param['filter'])
            ->page($page[0], $page[1])
            ->order($order)
            ->field(build_complex_query_fields($fields, '__'))
            ->select();

        $taskIds = array_column($taskData['rows'], 'task__id');
        $resData = [
            'rows' => [],
            'total' => $taskData['total'],
        ];
        if (empty($taskData['rows']) && !$isFirstActiveTask) {
            return $resData;
        }

        // 获取查询ids
        $filterStepCategoryIds = $filterStepIds = $filterUserIds = $filterEpisodeCodeList = $taskIdList = $parentEntityIdList = $taskStatusIdList = $taskTagIdList = [];

        $itemFormatter = function (&$row) use (&$filterStepCategoryIds, &$filterStepIds, &$filterUserIds, &$filterEpisodeCodeList, &$taskIdList, &$parentEntityIdList, &$taskStatusIdList, &$taskTagIdList) {
            $row = separate_complex_query_data($row, '__');
            if (!empty($row['task']['step_category_id'])) {
                $filterStepCategoryIds[$row['task']['step_category_id']] = $row['task']['step_category_id'];
            }
            if (!empty($row['task']['step_id'])) {
                $filterStepIds[$row['task']['step_id']] = $row['task']['step_id'];
            }
            if (!empty($row['task']['assignee'])) {
                $filterUserIds[$row['task']['assignee']] = $row['task']['assignee'];
            }
            if (!empty($row['task']['executor'])) {
                $filterUserIds[$row['task']['executor']] = $row['task']['executor'];
            }
            if (!empty($row['task']['created_by'])) {
                $filterUserIds[$row['task']['created_by']] = $row['task']['created_by'];
            }
            $filterEpisodeCodeList[$row['entity']['project_id']][] = $row['entity']['initial_episode_code'];
            $parentEntityIdList[$row['entity']['entity_id']] = $row['entity']['entity_id'];
            $taskIdList[] = $row['task']['id'];
            if ((int)$row['task']['task_status'] > 0) {
                $taskStatusIdList[$row['task']['task_status']] = $row['task']['task_status'];
            }
            if (!empty($row['task']['task_tag'])) {
                $row['task']['task_tag'] = explode(',', $row['task']['task_tag']);
            } else {
                $row['task']['task_tag'] = [];
            }
            foreach ($row['task']['task_tag'] as $taskTagId) {
                $taskTagIdList[$taskTagId] = $taskTagId;
            }
            $row['entity'] = CommonService::appendJsonFields($row['entity'], 'json');
        };

        // 获取所有子任务
        $dismantleTaskData = DismantleTaskService::getInstance()->getDismantleTaskIds($taskIds);
        $isDismantleTaskList = array_group_by($dismantleTaskData, 'source_task_id');
        foreach ($taskData['rows'] as &$row) {
            $itemFormatter($row);
        }
        if (!empty($activeTaskItem)) {
            //置顶在第一页
            if ($firstPage) {
                $itemFormatter($activeTaskItem);
                $activeTaskItem['time_log'] = $timelogTaskData;
                array_unshift($taskData['rows'], $activeTaskItem);
            }
            $taskData['total'] += 1;
        }

        unset($parentEntityIdList[0], $filterUserIds[0], $filterStepIds[0], $filterStepCategoryIds[0], $taskTagIdList[0], $taskTagIdList['']);

        // episode 集查询
        $episodeMap = [];
        if (!empty($filterEpisodeCodeList)) {
            $episodeMap = EpisodeService::getInstance()->getMultipleProjectEpisodes($filterEpisodeCodeList);
        }

        // parent entity 查询
        $parentEntityMap = [];
        if (!empty($parentEntityIdList)) {
            $parentEntityList = model(EntityModel::class)->where(['id' => ['IN', implode(',', $parentEntityIdList)]])->field("id,name,code,json,initial_episode_code,module_id")->select();
            if (!empty($parentEntityList)) {
                $parentEntityMap = array_column($parentEntityList, null, 'id');
                $parentEntityMap = array_map(function ($item) {
                    return CommonService::appendJsonFields($item, 'json');
                }, $parentEntityMap);
            }
        }

        // latest version
        $versionMap = $this->queryMaxVersionData($taskIdList, $filterUserIds);

        //task attr
        $taskAttr = InsideTaskReviewWorkflowService::getInstance()->getMultipleTaskAttr($taskIdList);

        // 填充 step
        $stepDict = [];
        if (!empty($filterStepIds)) {
            $stepData = model(StepModel::class)->field('id,name,code,color,can_multiple_submit,need_assemble')->where(['id' => ['IN', join(',', $filterStepIds)]])->select();
            $stepDict = array_column($stepData, null, 'id');
        }

        // 填充 step_category
        $stepCategoryDict = [];
        if (!empty($filterStepCategoryIds)) {
            $stepCategoryData = model(StepCategoryModel::class)->field('id,name,code')->where(['id' => ['IN', join(',', $filterStepCategoryIds)]])->select();
            $stepCategoryDict = array_column($stepCategoryData, null, 'id');
        }

        // 填充用户信息
        $userDict = [];
        if (!empty($filterUserIds)) {
            $userData = model(UserModel::class)->field('id,name,phone,union_id,avatar')->where(['id' => ['IN', join(',', $filterUserIds)]])->select();
            $userDict = array_column($userData, null, 'id');
        }

        // 任务状态
        $statusMap = [];
        if (!empty($taskStatusIdList)) {
            $statusList = model(StatusModel::class)->where(['id' => ['IN', array_values($taskStatusIdList)]])->select();
            $statusMap = array_column($statusList, null, 'id');
        }

        // tag查询
        $tagMap = [];
        if (!empty($taskTagIdList)) {
            $tagMap = model(TagModel::class)->where(['id' => ['IN', implode(',', $taskTagIdList)]])->select();
            $tagMap = array_column($tagMap, null, 'id');
        }

        // 数据回填
        foreach ($taskData['rows'] as $taskItem) {

            if (!empty($taskItem['task']['step_category_id']) && !empty($stepCategoryDict[$taskItem['task']['step_category_id']])) {
                $taskItem['step_category'] = $stepCategoryDict[$taskItem['task']['step_category_id']];
            } else {
                $taskItem['step_category'] = [
                    'id' => null,
                    'name' => null,
                    'code' => null
                ];
            }

            //填充任务属性
            $taskItem['task']['task_attr'] = $taskAttr[$taskItem['task']['id']] ?? '';

            if (!empty($taskItem['task']['step_id']) && !empty($stepDict[$taskItem['task']['step_id']])) {
                $taskItem['step'] = $stepDict[$taskItem['task']['step_id']];
            } else {
                $taskItem['step'] = [
                    'id' => null,
                    'name' => null,
                    'code' => null,
                    'color' => null
                ];
            }

            if (!empty($taskItem['task']['assignee']) && !empty($userDict[$taskItem['task']['assignee']])) {
                $taskItem['assignee'] = $userDict[$taskItem['task']['assignee']];
            } else {
                $taskItem['assignee'] = [
                    'id' => null,
                    'name' => null,
                    'phone' => null,
                    'union_id' => null
                ];
            }

            if (!empty($taskItem['task']['executor']) && !empty($userDict[$taskItem['task']['executor']])) {
                $taskItem['executor'] = $userDict[$taskItem['task']['executor']];
            } else {
                $taskItem['executor'] = [
                    'id' => null,
                    'name' => null,
                    'phone' => null,
                    'union_id' => null
                ];
            }

            if (!empty($taskItem['task']['created_by']) && !empty($userDict[$taskItem['task']['created_by']])) {
                $taskItem['created_by'] = $userDict[$taskItem['task']['created_by']];
            } else {
                $taskItem['created_by'] = [
                    'id' => null,
                    'name' => null,
                    'phone' => null,
                    'union_id' => null
                ];
            }
            $taskItem['task']['is_active'] = $taskItem['task']['id'] == $timelogTaskId;

            if (isset($taskItem['task']['task_status']) && !empty($statusMap[$taskItem['task']['task_status']])) {
                $taskItem['task_status'] = $statusMap[$taskItem['task']['task_status']];
            } else {
                $taskItem['task_status'] = null;
            }

            $tagsTmp = [];
            if (!empty($taskItem['task']['task_status'])) {
                $tagsTmp[] = array_merge(['tag_type' => "task_status"], $taskItem['task_status']);
            }

            if (!empty($taskItem['task']['task_tag'])) {

                $tags = [];
                foreach ($taskItem['task']['task_tag'] as $tagId) {
                    if (isset($tagMap[$tagId])) {
                        $tags[] = array_merge($tagMap[$tagId], ['tag_type' => 'task_tag']);
                    }
                }
                $taskItem['task']['task_tag'] = $tags;
                $tagsTmp = array_merge($tagsTmp, $tags);
            }

            if (!empty($taskItem['step'])) {
                $tagsTmp[] = array_merge(['tag_type' => "step"], $taskItem['step']);
            }

            $taskItem['latest_version'] = null;
            // 最新版本信息
            if (isset($versionMap[$taskItem['task']['id']])) {
                $taskItem['latest_version'] = $versionMap[$taskItem['task']['id']];
                $taskItem['latest_version']['current_reviewer'] = null;
                if (isset($taskItem['latest_version']['next_reviewer_user_id'])) {
                    $taskItem['latest_version']['current_reviewer'] = $userDict[$taskItem['latest_version']['next_reviewer_user_id']] ?? null;
                }
                $taskItem['latest_version']['last_reviewer'] = null;
                if (isset($taskItem['latest_version']['last_reviewer_user_id'])) {
                    $taskItem['latest_version']['last_reviewer'] = $userDict[$taskItem['latest_version']['last_reviewer_user_id']] ?? null;
                }
                $taskItem['latest_version']['reviewer_name'] = !empty($taskItem['latest_version']['last_reviewer']) ? $taskItem['latest_version']['last_reviewer']['name'] : null;
            }

            // 集信息
            $taskItem['episode'] = $episodeMap[$taskItem['entity']['project_id']][$taskItem['entity']['initial_episode_code']] ?? null;

            // 父级实体信息
            if (isset($parentEntityMap[$taskItem['entity']['entity_id']])) {
                $parentEntity = $parentEntityMap[$taskItem['entity']['entity_id']];
                $taskItem[Module::$moduleDictData['module_index_by_id'][$parentEntity['module_id']]['code']] = $parentEntity;
            }

            //最新版本
            if (!empty($taskItem['latest_version'])) {
                $tagsTmp[] = [
                    'id' => $taskItem['latest_version']['id'],
                    'code' => "",
                    'name' => "v" . $taskItem['latest_version']['number'],
                    'tag_type' => "task_version"
                ];
            }
            // 处理task.json 数据
            if (!empty($taskItem['task']['json'])) {
                $taskJson = json_decode($taskItem['task']['json'], true);
                $taskItem['task']['dismantle_name'] = $taskJson['dismantle_name'] ?? null;
                $taskItem['task']['is_dismantle_task'] = $taskJson['is_dismantle_task'] ?? null;
                $taskItem['task']['dismantle_task_ids'] = $isDismantleTaskList[$taskItem['task']['id']] ?? [];
            }
            $taskItem['tags'] = $tagsTmp;
            $resData['rows'][] = $taskItem;
        }

        $resData['total'] = $taskData['total'];

        return $resData;
    }

}
